package role

import (
	"fmt"
	"go.getaway.adminspro.padmins.com/untils"
	"go.getaway.adminspro.padmins.com/untils/handler"
	"strings"
)

func Index(c *handler.Handler) (map[string]interface{}, untils.Error) {
	where, bindValue, limit, order, e := c.BusinessCommonQuery.Build()
	if e != nil {
		return nil, untils.BusinessErrorf(e.Error())
	}

	params := map[string]string{
		"admin_id": fmt.Sprintf("%v", c.Auth.Get("id")),
	}

	authRoleIds := []interface{}{}

	if params["admin_id"] != "" {
		roleIds := c.Auth.GetChildrenRoleIds(params["admin_id"], true)
		where += " and id in (?)"
		bindValue = append(bindValue, roleIds)
		authRoleIds = c.Auth.GetRoleIdsByAdminId(params["admin_id"])
	}

	total, _ := c.Db.Find(fmt.Sprintf("select count(*) total from admin_role where 1=1 %s", where), bindValue...)
	rows, e := c.Db.Query(fmt.Sprintf("select * from admin_role where 1=1 %s %s %s", where, order, limit), bindValue...)
	if e != nil {
		return nil, untils.NewBusinessError(2000, e.Error())
	}
	fieldText := list()

	ids := untils.ArrayColumn(rows, "id")

	for _, row := range rows {
		c.ListFormat(fieldText, row)

		row["disabled"] = 0
		if untils.InArray(row["id"].(int64), authRoleIds) {
			row["disabled"] = 1
		}
		row["pid_original"] = row["pid"]
		if !untils.InArray(row["pid"].(int64), ids) {
			row["pid"] = 0
		}
	}

	return map[string]interface{}{
		"total": total["total"],
		"rows":  rows,
	}, nil
}

func list() map[string]interface{} {
	return map[string]interface{}{
		"status": map[string]interface{}{"0": "隐藏", "1": "显示"},
	}
}

func List(c *handler.Handler) (map[string]interface{}, untils.Error) {
	return list(), nil
}

func Detail(c *handler.Handler) (map[string]interface{}, untils.Error) {
	params := map[string]string{
		"admin_id": fmt.Sprintf("%v", c.Auth.Get("id")),
		"id":       fmt.Sprintf("%v", c.Request.Params("id", "")),
	}

	row, _ := c.Db.Find("select * from admin_role where id=?", params["id"])

	if row == nil {
		return nil, untils.BusinessErrorf("记录不存在")
	}

	if params["admin_id"] != "" {
		roleIds := c.Auth.GetChildrenRoleIds(params["admin_id"], true)
		if !untils.InArray(params["id"], roleIds) {
			return nil, untils.BusinessErrorf("没有权限查看")
		}
	}

	resourceRows, e := c.Db.Query("select resource_id from admin_role_resource_access where role_id=?", row["id"])

	if e != nil {
		return nil, untils.NewBusinessError(2000, e.Error())
	}
	resourceIds := untils.ArrayColumn(resourceRows, "resource_id")
	resources := []map[string]interface{}{}

	if untils.InArray(0, resourceIds) {
		resources, e = c.Db.Query("select * from admin_resource order by weigh,path")
	} else {
		resources, e = c.Db.Query("select * from admin_resource where id in (?) order by weigh,path", resourceIds)
	}

	if e != nil {
		return nil, untils.NewBusinessError(2000, e.Error())
	}

	resourceIds = untils.ArrayColumn(resources, "id")

	for _, resource := range resources {
		if !untils.InArray(resource["pid"], resourceIds) {
			resource["pid"] = 0
		}
		resource["name"] = resource["title"]
	}
	c.ListFormat(list(), row)
	row["resources"] = resources
	return map[string]interface{}{
		"row": row,
	}, nil
}

func Add(c *handler.Handler) (map[string]interface{}, untils.Error) {
	params := map[string]string{
		"admin_id":    fmt.Sprintf("%v", c.Auth.Get("id")),
		"pid":         fmt.Sprintf("%v", c.Request.Params("pid", "0")),
		"name":        fmt.Sprintf("%v", c.Request.Params("name", "")),
		"resource_id": fmt.Sprintf("%v", c.Request.Params("resource_id", "")),
		"status":      fmt.Sprintf("%v", c.Request.Params("status", "1")),
	}

	if params["name"] == "" {
		return nil, untils.BusinessErrorf("角色组名称不能为空")
	}

	if !untils.InArray(params["status"], untils.ArrayKeysString(list()["status"])) {
		return nil, untils.BusinessErrorf("状态参数不合法")
	}

	roleIds := []interface{}{}
	if params["admin_id"] != "" {
		roleIds = c.Auth.GetChildrenRoleIds(params["admin_id"], true)
	} else {
		roleIds = c.Auth.GetChildrenRoleIdsByRoleId(int64(0), false)
	}

	if !untils.InArray(params["pid"], roleIds) {
		return nil, untils.BusinessErrorf("上级ID错误")
	}

	has, _ := c.Db.Find("select * from admin_role where name=?", params["name"])

	if has != nil {
		return nil, untils.BusinessErrorf("角色名称已存在")
	}

	_, e := c.Db.TransactionFunc(func() (interface{}, error) {
		Result, e := c.Db.Execute("insert into admin_role(pid, name, status, update_time, create_time)"+
			"values(?, ?, ?, ?, ?)", []interface{}{
			params["pid"],
			params["name"],
			params["status"],
			untils.Date("Y-m-d H:i:s"),
			untils.Date("Y-m-d H:i:s"),
		}...)

		if e != nil {
			return nil, untils.NewBusinessError(2000, "insert failed: %v", e)
		}

		id, e := Result.LastInsertId()

		if e != nil {
			return nil, untils.NewBusinessError(2000, "LastInsertId failed: %v", e)
		}

		if params["resource_id"] != "" {
			resourceIds := strings.Split(params["resource_id"], ",")

			bindValue := []interface{}{}
			insertValue := ""

			for _, resourceId := range resourceIds {
				insertValue += "(?,?,?,?),"
				bindValue = append(bindValue, id)
				bindValue = append(bindValue, resourceId)
				bindValue = append(bindValue, untils.Date("Y-m-d H:i:s"))
				bindValue = append(bindValue, untils.Date("Y-m-d H:i:s"))
			}

			Result, e = c.Db.Execute("insert into admin_role_resource_access(role_id, resource_id, update_time, create_time)"+
				"values"+strings.Trim(insertValue, ","), bindValue...)

			if e != nil {
				return nil, untils.NewBusinessError(2000, "insert failed: %v", e)
			}

			rowCount, e := Result.RowsAffected()
			if e != nil {
				return nil, untils.NewBusinessError(2000, "LastInsertId failed: %v", e)
			}
			if rowCount <= 0 {
				return nil, untils.BusinessErrorf("操作失败")
			}
		}

		return nil, nil
	})

	if e != nil {
		return nil, untils.NewBusinessError(2000, e.Error())
	}

	return map[string]interface{}{}, nil
}

func Edit(c *handler.Handler) (map[string]interface{}, untils.Error) {
	params := map[string]string{
		"admin_id":    fmt.Sprintf("%v", c.Auth.Get("id")),
		"id":          fmt.Sprintf("%v", c.Request.Params("id", "0")),
		"pid":         fmt.Sprintf("%v", c.Request.Params("pid", "0")),
		"name":        fmt.Sprintf("%v", c.Request.Params("name", "")),
		"resource_id": fmt.Sprintf("%v", c.Request.Params("resource_id", "")),
		"status":      fmt.Sprintf("%v", c.Request.Params("status", "1")),
	}
	if params["name"] == "" {
		return nil, untils.BusinessErrorf("角色组名称不能为空")
	}

	if !untils.InArray(params["status"], untils.ArrayKeysString(list()["status"])) {
		return nil, untils.BusinessErrorf("状态参数不合法")
	}

	roleIds := []interface{}{}
	if params["admin_id"] != "" {
		roleIds = c.Auth.GetChildrenRoleIds(params["admin_id"], true)
		if !untils.InArray(params["pid"], roleIds) {
			return nil, untils.BusinessErrorf("不能操作不属于当前管理员的角色组")
		}
	}

	roleIds = c.Auth.GetChildrenRoleIdsByRoleId(params["id"], true)
	if untils.InArray(params["pid"], roleIds) {
		return nil, untils.BusinessErrorf("上级角色组ID不能为当前角色组的下级ID")
	}

	has, _ := c.Db.Find("select * from admin_role where name=? and id <> ?", params["name"], params["id"])

	if has != nil {
		return nil, untils.BusinessErrorf("角色名称已存在")
	}

	row, _ := c.Db.Find("select * from admin_role where id=?", params["id"])

	if row == nil {
		return nil, untils.BusinessErrorf("未找到记录")
	}

	_, e := c.Db.TransactionFunc(func() (interface{}, error) {
		Result, e := c.Db.Execute("update admin_role set name=?,pid=?,status=?,update_time=? where id=?", []interface{}{
			params["name"],
			params["pid"],
			params["status"],
			untils.Date("Y-m-d H:i:s"),
			params["id"],
		}...)

		if e != nil {
			return nil, untils.NewBusinessError(2000, "update failed: %v", e)
		}
		rowCount, _ := Result.RowsAffected()
		if rowCount == 0 {
			return nil, untils.BusinessErrorf("操作失败")
		}
		hasResource, e := c.Db.Query("select resource_id from admin_role_resource_access where role_id=?", row["id"])
		if e != nil {
			return nil, untils.NewBusinessError(2000, "select failed: %v", e)
		}

		hasResourceIds := untils.ArrayColumn(hasResource, "resource_id")
		aResourceIds := strings.Split(params["resource_id"], ",")
		resourceIds := make([]interface{}, len(aResourceIds))
		for _, resourceId := range aResourceIds {
			resourceIds = append(resourceIds, resourceId)
		}
		resourceIds = untils.ArrayFilter(resourceIds, func(val interface{}) bool {
			return val != "" && val != nil
		})
		addResourceId := untils.ArrayDiff(resourceIds, hasResourceIds)
		delResourceId := untils.ArrayDiff(hasResourceIds, resourceIds)

		if len(delResourceId) > 0 {
			Result, e := c.Db.Execute("delete from admin_role_resource_access where role_id=? and resource_id in (?)", row["id"], delResourceId)

			if e != nil {
				return nil, untils.NewBusinessError(2000, "操作失败%s", e)
			}
			rowCount, e := Result.RowsAffected()
			if e != nil {
				return nil, untils.NewBusinessError(2000, "操作失败%s", e)
			}
			if rowCount <= 0 {
				return nil, untils.BusinessErrorf("操作失败")
			}
		}

		for _, resourceId := range addResourceId {
			if fmt.Sprintf("%v", resourceId) == "0" {
				return nil, untils.BusinessErrorf("权限ID不能小于等于0")
			}

			Result, e := c.Db.Execute("insert into admin_role_resource_access(role_id, resource_id, update_time, create_time)"+
				"values (?, ?, ?, ?)", row["id"], resourceId, untils.Date("Y-m-d H:i:s"), untils.Date("Y-m-d H:i:s"))

			if e != nil {
				return nil, untils.NewBusinessError(2000, "操作失败:%v", e)
			}

			rowCount, e := Result.RowsAffected()

			if e != nil {
				return nil, untils.NewBusinessError(2000, "操作失败:%v", e)
			}

			if rowCount <= 0 {
				return nil, untils.BusinessErrorf("操作失败")
			}
		}

		return nil, nil
	})

	if e != nil {
		return nil, untils.NewBusinessError(2000, e.Error())
	}

	return map[string]interface{}{}, nil
}

func Del(c *handler.Handler) (map[string]interface{}, untils.Error) {
	params := map[string]string{
		"admin_id": fmt.Sprintf("%v", c.Auth.Get("id")),
		"id":       fmt.Sprintf("%v", c.Request.Params("id")),
	}

	aId := strings.Split(params["id"], ",")
	ids := []interface{}{}
	for _, id := range aId {
		ids = append(ids, id)
	}

	if params["admin_id"] != "" {
		roleIds := c.Auth.GetChildrenRoleIds(params["admin_id"], true)
		fmt.Println(ids, untils.ArrayDiff(ids, roleIds))
		if len(untils.ArrayDiff(ids, roleIds)) > 0 {
			return nil, untils.BusinessErrorf("不能删除自己的角色")
		}
	}

	has, _ := c.Db.Find("select * from admin_role_access where role_id in (?)", ids)

	if has != nil {
		return nil, untils.BusinessErrorf("角色组中有管理员不能操作")
	}

	row, _ := c.Db.Find("select * from admin_role where id in (?)", ids)

	if row == nil {
		return nil, untils.BusinessErrorf("未找到记录")
	}

	c.Db.TransactionFunc(func() (interface{}, error) {
		Result, e := c.Db.Execute("delete from admin_role where id in (?)", ids)

		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}

		rowCount, e := Result.RowsAffected()

		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}

		if rowCount <= 0 {
			return nil, untils.BusinessErrorf("操作失败")
		}

		Result, e = c.Db.Execute("delete from admin_role_resource_access where role_id in (?)", ids)

		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}

		rowCount, e = Result.RowsAffected()

		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}

		if rowCount <= 0 {
			return nil, untils.BusinessErrorf("操作失败")
		}

		return nil, nil
	})

	return map[string]interface{}{}, nil
}

func Multi(c *handler.Handler) (map[string]interface{}, untils.Error) {
	return nil, untils.BusinessErrorf("没有权限操作")
}

func Resource(c *handler.Handler) (map[string]interface{}, untils.Error) {
	params := map[string]string{
		"pid": fmt.Sprintf("%v", c.Request.Params("pid")),
		"id":  fmt.Sprintf("%v", c.Request.Params("id")),
	}
	rows, e := c.Db.Query("select resource_id from admin_role_resource_access where role_id in (?)", params["pid"])
	if e != nil {
		return nil, untils.NewBusinessError(2000, e.Error())
	}

	resourceIds := untils.ArrayColumn(rows, "resource_id")
	selectResourceIds := []interface{}{}
	if params["id"] != "" {
		rows, e := c.Db.Query("select resource_id from admin_role_resource_access where role_id in (?)", params["id"])
		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}
		selectResourceIds = untils.ArrayColumn(rows, "resource_id")
	}

	if untils.InArray(int64(0), resourceIds) {
		rows, e = c.Db.Query("select * from admin_resource")
		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}
	} else {
		rows, e = c.Db.Query("select * from admin_resource where id in (?)", resourceIds)
		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}
	}

	ids := untils.ArrayColumn(rows, "id")
	pids := untils.ArrayColumn(rows, "pid")

	for _, row := range rows {
		if !untils.InArray(row["pid"], ids) {
			row["pid"] = 0
		}
		if !untils.InArray(row["id"], pids) {
			row["selected"] = untils.InArray(row["id"], selectResourceIds)
		}
	}

	return map[string]interface{}{
		"total": len(rows),
		"rows":  rows,
	}, nil
}
